package com.boful.common.reflect.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Arrays;

/***
 * 对象工具
 * 
 * @author ligson
 * 
 */
public class BofulClassUtils {

	/***
	 * 对象赋值，把src的属性赋给dest的属性
	 * 
	 * @param src
	 *            源对象
	 * @param dest
	 *            目标对象
	 * @param ignored
	 *            忽略的属性
	 */
	public static void cloneObject(Object src, Object dest, String[] ignored) {
		Class<?> class1 = src.getClass();
		Class<?> class2 = dest.getClass();
		Field[] fields1 = class1.getDeclaredFields();
		Field[] fields2 = class2.getDeclaredFields();
		// Method[] methods1 = class1.getDeclaredMethods();
		Method[] methods2 = class2.getDeclaredMethods();

		for (Field field : fields1) {

			String fieldName1 = field.getName();
			if (ignored != null && ignored.length > 0) {
				if (Arrays.binarySearch(ignored, fieldName1) < 0) {
					continue;
				}
			}

			boolean isContain = false;
			for (Field field2 : fields2) {
				if (field2.getName().equals(fieldName1)) {
					isContain = true;
					break;
				}
			}

			if (isContain) {
				isContain = false;
				String setMethodName = "set"
						+ fieldName1.substring(0, 1).toUpperCase()
						+ fieldName1.substring(1);
				String getMethod = "get";
				if ((field.getType() == Boolean.class)
						|| (field.getType() == boolean.class)) {
					getMethod = "is";
				}
				String getMethodName = getMethod
						+ fieldName1.substring(0, 1).toUpperCase()
						+ fieldName1.substring(1);

				for (Method method : methods2) {

					if (method.getName().equals(setMethodName)) {
						if (method.getReturnType() == void.class) {
							if (method.getModifiers() == Modifier.PUBLIC) {
								Class<?>[] paramTypes = method
										.getParameterTypes();
								if ((paramTypes.length == 1)
										&& (paramTypes[0] == field.getType())) {
									try {
										Method getMehod = class1
												.getMethod(getMethodName);
										Object value = getMehod.invoke(src);
										Method method2 = class2.getMethod(
												setMethodName, field.getType());
										method2.invoke(dest, value);
									} catch (Exception e) {
										e.printStackTrace();
									}
								}
							}
						}
					}
				}
			}
		}
	}

	/***
	 * 对象赋值，把src的属性赋给dest的属性
	 * 
	 * @param src
	 *            源对象
	 * @param dest
	 *            目标对象
	 */
	public static void cloneObject(Object src, Object dest) {
		cloneObject(src, dest, null);
	}

	/***
	 * 如果对象object有properties中的属性名称，则把properties中的对应的属性在values中对应的值赋给object
	 * 
	 * @param properties
	 *            属性名称集合
	 * @param values
	 *            属性对应的值
	 * @param object
	 *            目标赋值对象
	 */
	public static void evaluate(String[] properties, Object[] values,
			Object object) throws Exception {
		if (properties.length != values.length) {
			throw new Exception("属性名称和值集合长度不一致");
		}
		Class<?> clazz = object.getClass();
		Field[] fields = clazz.getDeclaredFields();
		for (String propertyName : properties) {
			Field field = null;
			int index = 0;
			for (int i = 0; i < fields.length; i++) {
				Field field2 = fields[i];
				if (field2.getName().equals(propertyName)) {
					field = field2;
					index = i;
					break;
				}
			}
			if (field != null) {
				String setMethodName = getSetMethodName(field);
				Class<?> paramType = values[index].getClass();
				try {
					Method method = clazz.getDeclaredMethod(setMethodName,
							paramType);
					if (method != null) {
						method.invoke(object, values[index]);
					}
				} catch (NoSuchMethodException e) {
					Method method = null;
					try {
						if (paramType == Integer.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									int.class);
						} else if (paramType == Boolean.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									boolean.class);
						} else if (paramType == long.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									Long.class);
						} else if (paramType == Short.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									Short.class);
						} else if (paramType == Byte.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									byte.class);
						} else if (paramType == Double.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									double.class);
						} else if (paramType == Float.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									float.class);
						} else if (paramType == Character.class) {
							method = clazz.getDeclaredMethod(setMethodName,
									char.class);
						}
					} catch (Exception e2) {

					}
					if (method != null) {
						method.invoke(object, values[index]);
					}

				}

			}

		}
	}

	/***
	 * 获取get方法名
	 * 
	 * @param field
	 *            字段名称
	 * @return get方法名
	 */
	public static String getGetMethodName(Field field) {
		String fieldName = field.getName();

		String getMethod = "get";
		if ((field.getType() == Boolean.class)
				|| (field.getType() == boolean.class)) {
			getMethod = "is";
		}
		String getMethodName = getMethod
				+ fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
		return getMethodName;
	}

	/***
	 * 获取set方法名
	 * 
	 * @param field
	 *            字段名称
	 * @return set方法名
	 */
	public static String getSetMethodName(Field field) {
		String fieldName = field.getName();
		String setMethodName = "set" + fieldName.substring(0, 1).toUpperCase()
				+ fieldName.substring(1);
		return setMethodName;
	}

}
